import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart' hide Response, FormData, MultipartFile;
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import '../index.dart';
import '../utils/error_handle.dart';

class HttpService extends GetxService {

  static HttpService get to => Get.find();

  late final Dio _dio;

  @override
  void onInit() {
    super.onInit();
    // 初始 dio
    var options = BaseOptions(
      baseUrl: Constants.baseUrl,
      connectTimeout: const Duration(seconds: 60), // 10000, // 10秒
      receiveTimeout: const Duration(seconds: 60), // 5000, // 5秒
      headers: {},
      contentType: 'application/json; charset=utf-8',
      responseType: ResponseType.json,
    );
    _dio = Dio(options);

    // 添加request拦截器
    _dio.interceptors.add(RequestInterceptors());
    // _dio.interceptors.add(LoggingInterceptor());
    // 添加请求日志输出拦截器
    _dio.interceptors.add(PrettyDioLogger(
      requestHeader: true,
      requestBody: true,
      responseHeader: true,
      responseBody: true,
      error: true,
      maxWidth: 90,
      logPrint: (Object object) {
        debugPrint(object.toString());
      },
    ));

    // 配置缓存拦截器
    CacheStore cacheStore =
        MemCacheStore(maxSize: 10485760, maxEntrySize: 1048576);
    CacheOptions cacheOptions = CacheOptions(
      store: cacheStore,
      hitCacheOnErrorExcept: [], // for offline behaviour
    );
    final cacheInterceptor = DioCacheInterceptor(options: cacheOptions);
    _dio.interceptors.add(cacheInterceptor);
  }

  Future<Response> get(
    String url, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    bool? cache,
    dynamic cacheArgs,
    bool? loading,
    bool? dismiss,
  }) async {
    Options requestOptions = options ?? Options();
    if (loading == true) Loading.request();

    /// 展示loading
    Response response = await _dio.get(
      url,
      queryParameters: params,
      options: requestOptions,
      cancelToken: cancelToken,
    );

    /// 保存缓存
    _saveCache(url, response,
        cacheArgs: cacheArgs, cache: cache, dismiss: dismiss);
    return response;
  }

  /// 保存缓存
  void _saveCache(
    String url,
    Response response, {
    dynamic cacheArgs,
    bool? cache,
    bool? dismiss,
  }) {
    /// loading消失(立马消失)
    if (dismiss == true) Loading.dismiss(milliseconds: 0);
    if (cache == true) {
      try {
        if (response.data['code'] == 0) {
          /// 缓存数据(缓存第一屏数据，不需要参数)
          DataCacheUtil.share()
              .saveCacheData(url, response.data['data'], params: cacheArgs);
        }
      } catch (err) {
        throw ('缓存数据异常,请检查数据格式及参数(Map<String,dynamic>)');
      }
    }
  }

  Future<Response> post(
    String url, {
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
    bool? cache,
    dynamic cacheArgs,
    bool? loading,
    bool? dismiss,
  }) async {
    var requestOptions = options ?? Options();
    if (loading == true) Loading.request();

    /// 展示loading
    Response response = await _dio.post(
      url,
      data: data ?? {},
      options: requestOptions,
      cancelToken: cancelToken,
    );

    /// 保存缓存
    _saveCache(url, response,
        cacheArgs: cacheArgs, cache: cache, dismiss: dismiss);
    return response;
  }

  Future<Response> put(
    String url, {
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
    bool? cache,
    dynamic cacheArgs,
    bool? loading,
    bool? dismiss,
  }) async {
    var requestOptions = options ?? Options();
    if (loading == true) Loading.request();

    /// 展示loading
    Response response = await _dio.put(
      url,
      data: data ?? {},
      options: requestOptions,
      cancelToken: cancelToken,
    );

    /// 保存缓存
    _saveCache(url, response,
        cacheArgs: cacheArgs, cache: cache, dismiss: dismiss);
    return response;
  }

  Future<Response> delete(
    String url, {
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
    bool? cache,
    dynamic cacheArgs,
    bool? loading,
    bool? dismiss,
  }) async {
    var requestOptions = options ?? Options();
    if (loading == true) Loading.request();

    /// 展示loading
    Response response = await _dio.delete(
      url,
      data: data ?? {},
      options: requestOptions,
      cancelToken: cancelToken,
    );

    /// 保存缓存
    _saveCache(url, response,
        cacheArgs: cacheArgs, cache: cache, dismiss: dismiss);
    return response;
  }
}

class LoggingInterceptor extends Interceptor {
  late DateTime _startTime;
  late DateTime _endTime;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    _startTime = DateTime.now();
    debugPrint('----------Start----------');
    if (options.queryParameters.isEmpty) {
      debugPrint('RequestUrl: ${options.baseUrl}${options.path}');
    } else {
      debugPrint(
          'RequestUrl: ${options.baseUrl}${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
    }
    debugPrint('RequestMethod: ${options.method}');
    debugPrint('RequestHeaders:${options.headers}');
    debugPrint('RequestContentType: ${options.contentType}');
    debugPrint('RequestData: ${options.data.toString()}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    _endTime = DateTime.now();
    final int duration = _endTime.difference(_startTime).inMilliseconds;
    if (response.statusCode == ExceptionHandle.success) {
      debugPrint('ResponseCode: ${response.statusCode}');
    } else {
      debugPrint('ResponseCode: ${response.statusCode}');
    }
    // 输出结果
    debugPrint(response.data.toString());
    debugPrint('----------End: $duration 毫秒----------');
    super.onResponse(response, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    debugPrint('----------Error-----------');
    super.onError(err, handler);
  }
}

/// 拦截
class RequestInterceptors extends Interceptor {

  // 插入基础header信息
  void _insertHeaders(RequestOptions options){
    // 版本号
    options.headers['version'] = ConfigService.to.version;
    // 平台
    options.headers['platform'] = kIsWeb ? "WEB" : Platform.isIOS ? "IOS" : "ANDROID";
    // 设备信息
    options.headers['deviceId'] = ConfigService.to.deviceID;
    // 设备系统
    options.headers['systemVersion'] = ConfigService.to.systemVersion;
  }

  // 请求拦截
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // super.onRequest(options, handler);
    // http header 头加入信息
    _insertHeaders(options);
    return handler.next(options);
    // 如果你想完成请求并返回一些自定义数据，你可以resolve一个Response对象 `handler.resolve(response)`。
    // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义response.
    //
    // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,如`handler.reject(error)`，
    // 这样请求将被中止并触发异常，上层catchError会被调用。
  }

  // 响应拦截
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // 200 请求成功, 201 添加成功
    if (response.statusCode != 200 && response.statusCode != 201) {
      switch (response.statusCode) {
        case 401:
          /// 401 未登录，注销并跳转到登录页面
          if (EasyLoading.isShow) {
            EasyLoading.dismiss();
          }
          _errorNoAuthLogout();
          break;
        default:
          handler.reject(
            DioException(
              requestOptions: response.requestOptions,
              response: response,
              type: DioExceptionType.badResponse,
            ),
            true,
          );
          break;
      }
    } else {
      int? code = response.data['code'];
      if (code != null && code == 30006){
        // 加载泡消失
        Loading.dismiss(milliseconds: 0);
      }else {
        handler.next(response);
      }
    }
  }

  // 退出并重新登录
  Future<void> _errorNoAuthLogout() async {

  }

  // 错误拦截
  @override
  Future<void> onError(
      DioException err, ErrorInterceptorHandler handler) async {
    final exception = HttpException(err.message ?? "error message");
    Loading.dismiss(milliseconds: 0);

    /// 加载超时，隐藏加载框
    switch (err.type) {
      case DioExceptionType.badResponse: // 服务端自定义错误体处理
        {
          final responseData = err.response?.data;
          // final errorMessage = ErrorMessageModel.fromJson(response?.data);
          // log("[common/services/http]====错误statusCode：${errorMessage.statusCode}==code==${errorMessage.code}");
          // log("====报错接口：${response?.realUri}====$response");
          int? code = responseData['statusCode'] ??responseData['code'];
          debugPrint('===报错接口：');
          switch (code) {
            // 401 未登录
            case 401:
              // 注销 并跳转到登录页面
              _errorNoAuthLogout();
              break;
            case 404:

              break;
            case 500:
              break;
            case 502:
              break;
            default:
              break;
          }
          // 请求错误拦截提示
          // Loading.error(errorMessage.message);
        }
        break;
      case DioExceptionType.unknown:
        break;
      case DioExceptionType.cancel:
        break;
      case DioExceptionType.connectionTimeout:
        Loading.error("连接超时");
        break;
      default:
        break;
    }
    DioException errNext = err.copyWith(
      error: exception,
    );
    handler.next(errNext);
  }
}
